<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/favicon.ico">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon.ico">
  <link rel="mask-icon" href="/images/favicon.ico" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"yoursite.com","root":"/","scheme":"Mist","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"always","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="面试复习">
<meta property="og:type" content="article">
<meta property="og:title" content="面试复习知识点记录(更新中)">
<meta property="og:url" content="http://yoursite.com/2019/02/14/android-2019-2-14-Review/index.html">
<meta property="og:site_name" content="Akiyama&#39;s Blog">
<meta property="og:description" content="面试复习">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://yoursite.com/images/Review/ActivityLifecycler.png">
<meta property="og:image" content="http://yoursite.com/images/Review/ServiceLifecycle.png">
<meta property="og:image" content="http://yoursite.com/images/Review/Android%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84.jpg">
<meta property="og:image" content="http://yoursite.com/images/Review/Android%E6%89%93%E5%8C%85%E6%B5%81%E7%A8%8B.jpg">
<meta property="og:image" content="http://yoursite.com/images/Review/%E8%87%AA%E5%AE%9A%E4%B9%89View%E7%BB%98%E5%88%B6%E9%A1%BA%E5%BA%8F.jpg">
<meta property="article:published_time" content="2019-02-13T16:00:00.000Z">
<meta property="article:modified_time" content="2021-05-16T10:04:43.150Z">
<meta property="article:author" content="丘山月夜">
<meta property="article:tag" content="Android">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://yoursite.com/images/Review/ActivityLifecycler.png">

<link rel="canonical" href="http://yoursite.com/2019/02/14/android-2019-2-14-Review/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>面试复习知识点记录(更新中) | Akiyama's Blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Akiyama's Blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">丘山月夜的博客</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="home fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="user fa fa-user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="tags fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="th fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="archive fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/02/14/android-2019-2-14-Review/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="丘山月夜">
      <meta itemprop="description" content="君は空を見てるか,<br>風の音を聞いてるか">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Akiyama's Blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          面试复习知识点记录(更新中)
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-02-14 00:00:00" itemprop="dateCreated datePublished" datetime="2019-02-14T00:00:00+08:00">2019-02-14</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-05-16 18:04:43" itemprop="dateModified" datetime="2021-05-16T18:04:43+08:00">2021-05-16</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/" itemprop="url" rel="index"><span itemprop="name"></span></a>
                </span>
            </span>

          
            <div class="post-description">面试复习</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="1-四大组件"><a href="#1-四大组件" class="headerlink" title="1. 四大组件"></a>1. 四大组件</h1><h2 id="1-1-Activity：活动"><a href="#1-1-Activity：活动" class="headerlink" title="1.1. Activity：活动"></a>1.1. Activity：活动</h2><h3 id="1-1-1-四个状态"><a href="#1-1-1-四个状态" class="headerlink" title="1.1.1. 四个状态"></a>1.1.1. 四个状态</h3><ul>
<li>Running：Activity处于当前活动栈的栈顶。是可见的，可以与用户交互。</li>
<li>Paused：当Activity失去焦点，如出现弹窗Dialog，或者被一个透明的Activity覆盖时。</li>
<li>Stopped：Activity完全不可见，如退回主界面，或被另一个Activity覆盖。</li>
<li>Killed：Activity被销毁，即从Task中出栈。</li>
</ul>
<h3 id="1-1-2-七大生命周期"><a href="#1-1-2-七大生命周期" class="headerlink" title="1.1.2. 七大生命周期"></a>1.1.2. 七大生命周期</h3><p><img src="/images/Review/ActivityLifecycler.png" alt="Activity生命周期"></p>
<p><strong>具体情况分析</strong></p>
<p>ActivityA启动ActivityB时</p>
<blockquote>
<ol>
<li>先调用ActivityA的onPause</li>
<li>然后调用ActivityB的onCreate-&gt;onStart-&gt;onResume</li>
<li>然后调用ActivityA的onSavedInstanceState-&gt;onStop</li>
</ol>
</blockquote>
<p>back返回的时候</p>
<blockquote>
<ol>
<li>调用ActivityB的onPause</li>
<li>再调用ActivityA的onRestart-&gt;onStart-&gt;onResume</li>
<li>然后调用ActivityB的onStop-&gt;onDestroy</li>
</ol>
</blockquote>
<p>总结：要等后一个Activity完全显示出来（onResume），才会触发前一个Activity的onStop</p>
<h4 id="onSavedInstanceState：通过Bundle（key-value）保存Activity的实例，用于恢复页面意外销毁前的状态"><a href="#onSavedInstanceState：通过Bundle（key-value）保存Activity的实例，用于恢复页面意外销毁前的状态" class="headerlink" title="onSavedInstanceState：通过Bundle（key-value）保存Activity的实例，用于恢复页面意外销毁前的状态"></a>onSavedInstanceState：通过Bundle（key-value）保存Activity的实例，用于恢复页面意外销毁前的状态</h4><p>调用时机：当activity<strong>有可能</strong>被系统回收的情况下，在onStop之前执行。即Activity在后台（不在当前活动栈的栈顶，可能是在当前活动Task栈底，或者在其他Task中），内存不足时可能被回收。</p>
<p>注：</p>
<ul>
<li>如果必定被销毁，例如按下返回键或者调用finish方法手动销毁Activity，则不会调用onSavedInstanceState</li>
<li>onSavedInstanceState和onPause执行顺序不一定，但一定在onStop之前。</li>
<li>相反的，onRestoreInstanceState在onStart之后。</li>
</ul>
<p><strong>举例</strong></p>
<blockquote>
<ol>
<li>当按下Home键退回桌面时</li>
<li>打开新的Activity时（在当前活动Task栈底）</li>
<li>打开其他程序时，如跳到电话界面，或者从通知栏进入其他程序，或者打开后台显示切换到另一个程序（在其他Task中）</li>
<li>按下电源键关闭屏幕时</li>
<li>横竖屏切换时</li>
</ol>
</blockquote>
<h4 id="onRestoreInstanceState：获取onSavedInstanceState保存的数据，恢复页面状态"><a href="#onRestoreInstanceState：获取onSavedInstanceState保存的数据，恢复页面状态" class="headerlink" title="onRestoreInstanceState：获取onSavedInstanceState保存的数据，恢复页面状态"></a>onRestoreInstanceState：获取onSavedInstanceState保存的数据，恢复页面状态</h4><p>调用时机：只有在Activity确定是被<strong>系统</strong>回收后，<strong>重新创建</strong>Activity的时候才会被调用。</p>
<p>注：</p>
<ul>
<li>如果是手动销毁Activity，则不会被调用</li>
<li>反过来说，如果onRestoreInstanceState被调用了，则页面必然被系统回收过，onSavedInstanceState、onDestroy必然被调用过。因此重建的时候必然调用onCreate</li>
<li>onCreate中也能获取到onSavedInstanceState保存的实例，并且在super.onCreate进行恢复</li>
</ul>
<p>如果要恢复自己保存的数据的话，需要在onCreate中进行非空判断，如果为null，则说明是新的Activity实例，而不是被恢复的实例。onRestoreInstanceState不需要判断，因为他只有在activity被回收之后才会被调用。</p>
<p><strong>具体情况</strong></p>
<p>进行横竖屏切换时，生命周期如下</p>
<blockquote>
<p>onPause-&gt;onSavedInstanceState-&gt;onStop-&gt;onDestroy-&gt;onCreate-&gt;onStart-&gt;onRestoreInstanceState-&gt;onResume</p>
</blockquote>
<p>因为onCreate的super.onCreate中对横竖屏切换的状态进行了恢复，因此不需要实现onRestoreInstanceState</p>
<h4 id="横竖屏切换"><a href="#横竖屏切换" class="headerlink" title="横竖屏切换"></a>横竖屏切换</h4><p>如果在Manifest中设置了<code> android:configChanges=”orientation|keyboardHidden|screenSize”</code>，则不会调用各个生命周期，而是调用<code>onConfigurationChanged</code>方法</p>
<h3 id="1-1-3-四种启动方式（LaunchMode）"><a href="#1-1-3-四种启动方式（LaunchMode）" class="headerlink" title="1.1.3. 四种启动方式（LaunchMode）"></a>1.1.3. 四种启动方式（LaunchMode）</h3><p>任务栈（Task）、回退栈</p>
<blockquote>
<ol>
<li>用于存储当前程序的Activity。</li>
<li>当前运行的Task叫当前活动栈。当前运行的Activity在当前活动栈的栈顶。</li>
<li>退出应用时，把任务栈中的activity都销毁出栈，然后销毁任务栈</li>
<li>一个应用程序至少有一个任务栈，还可能有多个</li>
<li>Activity在栈内的顺序是可以控制的，通过启动方式和Intent Flag</li>
</ol>
</blockquote>
<p>配置LaunchMode</p>
<blockquote>
<ol>
<li>在AndroidManifest.xml配置的android:launchMode属性。</li>
<li>通过startActivity结合intent的flag属性</li>
</ol>
</blockquote>
<h4 id="standard模式"><a href="#standard模式" class="headerlink" title="standard模式"></a>standard模式</h4><p>默认的启动模式，每次启动Activity都会创建Activity实例，并放入任务栈。</p>
<h4 id="singleTop模式：栈顶复用"><a href="#singleTop模式：栈顶复用" class="headerlink" title="singleTop模式：栈顶复用"></a>singleTop模式：栈顶复用</h4><p>如果任务栈的栈顶正好存在该Activity的实例，就重用该实例，否则创建新的实例并放入栈顶。当重用了该实例的时候会调用onNewIntent方法。例如：点击通知打开页面</p>
<h4 id="singleTask模式：栈内复用"><a href="#singleTask模式：栈内复用" class="headerlink" title="singleTask模式：栈内复用"></a>singleTask模式：栈内复用</h4><p>如果任务栈中存在该实例，则不需要创建，会把该Activity以上的实例都pop销毁，一般用于首页</p>
<h4 id="singleInstance模式"><a href="#singleInstance模式" class="headerlink" title="singleInstance模式"></a>singleInstance模式</h4><p>新建一个栈并把Activity加入栈中，该Activity独占该栈（被它开启的Activity会加入其他栈）。整个系统中只有一个这样的实例，再次启动时（即使时另一个app）会重用该实例，并且调用onNewIntent方法。</p>
<p>注：在onNewIntent中设置了数据，需要使用setIntent(intent)保存下来，否则getIntent拿到的是老的Intent</p>
<p><strong>具体情况1</strong></p>
<blockquote>
<ol>
<li><p>B设置为singleInstance，A打开B，B打开C</p>
<ul>
<li>此时A和C在Task1中，B在Task2中。如果A和C的taskAffinity不相同的话，B会新建一个Task3来存放C</li>
</ul>
</li>
<li><p>点击返回</p>
<ul>
<li>C出栈，回到A页面</li>
</ul>
</li>
<li><p>再点一次返回</p>
<ul>
<li>A出栈，Task1销毁，回到B页面</li>
</ul>
</li>
</ol>
</blockquote>
<p><strong>具体情况2</strong></p>
<p>B设置为singleInstance，A启动B，按下Home键，点击图标进入app，回到页面A。从launcher打开应用的时候会启动默认的栈。</p>
<p><strong>具体情况3</strong></p>
<p>B设置为singleInstance，A启动C，C启动B，从B页面打开A，结果显示的是C，而不是A。</p>
<p>注：</p>
<ul>
<li>如果想让两个页面处于同一个栈，可以设置taskAffinity属性（任务归属），设置同样的栈名</li>
<li>starActivityForResult在5.0之后无论目标Activity设置什么模式，启动后都会强制放在当前栈顶</li>
</ul>
<h3 id="1-1-4-taskAffinity属性"><a href="#1-1-4-taskAffinity属性" class="headerlink" title="1.1.4. taskAffinity属性"></a>1.1.4. taskAffinity属性</h3><ul>
<li>Activity包含一个taskAffinity属性，表示该Activity归属的栈的名称。</li>
<li>具有相同taskAffinity的两个Activity处于同一个任务栈（即使是两个应用）</li>
<li>默认情况下，一个应用的所有Activity具有相同的taskAffinity，即应用程序包名。可以通过设置不同的taskAffinity进行分组，也可以把不同应用的Activity设置为相同的值</li>
<li>使用singleTask方式启动页面时，会检查名为taskAffinity的任务栈中是否存在该实例，如果存在，则重用并弹出在其上的所有Activity，如果不存在，则新建一个实例到名为taskAffinity的任务栈中</li>
</ul>
<h3 id="1-1-5-Intent的Flag属性"><a href="#1-1-5-Intent的Flag属性" class="headerlink" title="1.1.5. Intent的Flag属性"></a>1.1.5. Intent的Flag属性</h3><blockquote>
<ol>
<li>Intent.FLAG_ACTIVITY_NEW_TASK：如果taskAffinity和当前栈相同，则在当前栈新建一个Activity实例，如果不同，则新建一个栈存放Activity<ol>
<li>注：在非Activity的Context中启动Activity需要添加这个属性，否则会抛异常（在ContextImpl中），Activity重写了startActivity方法，因此不会抛异常</li>
</ol>
</li>
<li>FLAG_ACTIVITY_SINGLE_TOP：类似singleTop</li>
<li>FLAG_ACTIVITY_CLEAR_TOP：类似singleTask，将其上的Activity清除<ol>
<li>但是和SingleTask不一样的是，FLAG_ACTIVITY_CLEAR_TOP会把自身也销毁，然后重新实例化该Activity。而SingleTask会复用该Activity，只会触发onNewIntent，不触发onCreate。</li>
</ol>
</li>
<li>FLAG_ACTIVITY_REORDER_TO_FRONT：将栈内的Activity移到栈顶，不销毁其他Activity</li>
<li>FLAG_ACTIVITY_BROUGHT_TO_FRONT</li>
</ol>
</blockquote>
<h2 id="1-2-Service：服务"><a href="#1-2-Service：服务" class="headerlink" title="1.2. Service：服务"></a>1.2. Service：服务</h2><p>Service是Android中实现程序后台运行的解决方案，它非常适用于去执行那些不需要和用户交互而且还要求长期运行的任务。</p>
<blockquote>
<ol>
<li>Service默认并不会运行在子线程中，它也不运行在一个独立的进程中，<strong>本地服务</strong>默认在UI线程执行，但是Serivce一般都进行长期操作，为了避免阻塞UI线程或者防止ANR，<strong>一般会在Service中开启子线程执行任务</strong>。</li>
<li>Service的运行不依赖于任何用户界面，即使程序被切换到后台或者用户打开另一个应用程序，Service仍然能够保持正常运行，这也正是Service的使用场景。<strong>当某个应用程序进程被杀掉时，所有依赖于该进程的Service也会停止运行</strong></li>
<li>服务有两种启动方式：startService和bindService。两者可以同时使用</li>
<li>Service一旦创建，需要调用相应的停止方法，如<code>stopService() / stopSelf()、unbindService()</code>。如果两种启动方式同时使用，需要两个方法都调用，才会终止服务。</li>
<li>系统只有在内存紧张的时候才会销毁Service</li>
<li>为服务指定一个独立的进程：在manifest文件中设置android:process属性，此时服务称为<strong>远程服务</strong></li>
</ol>
</blockquote>
<p>生命周期（官方图）：</p>
<p><img src="/images/Review/ServiceLifecycle.png" alt="Service生命周期官方图"></p>
<h3 id="1-2-1-Service和Thread的区别"><a href="#1-2-1-Service和Thread的区别" class="headerlink" title="1.2.1. Service和Thread的区别"></a>1.2.1. Service和Thread的区别</h3><p>Thread是程序执行的最小单元，可以用Thread执行异步的操作。</p>
<ul>
<li>独立于Activity：当Activity被销毁，线程没有主动停止或者run方法没有执行完毕，Thread会一直执行</li>
<li>Activity销毁后，不再持有Thread的引用，无法对Thread进行控制。例如做心跳服务</li>
<li>另外，不同的Activity不能控制同一个Thread。</li>
</ul>
<p>Service是android提供的机制，本地服务是运行在主进程的（UI线程），远程服务是运行在独立进程的主线程</p>
<ul>
<li>只有一个Service实例，可以在任何有Context的地方控制同一个Service。</li>
</ul>
<h3 id="1-2-2-本地服务和远程服务"><a href="#1-2-2-本地服务和远程服务" class="headerlink" title="1.2.2. 本地服务和远程服务"></a>1.2.2. 本地服务和远程服务</h3><p>本地服务：依附在主进程而不是独立的进程。</p>
<blockquote>
<ol>
<li>节约了资源，并且不需要IPC。</li>
<li>主进程被Kill后，服务便终止。</li>
</ol>
</blockquote>
<p>远程服务：Service在独立的进程（在Manifest文件中设置android:process属性），对应进程为包名+android:process的值。</p>
<blockquote>
<ol>
<li>在Manifest文件中设置android:process属性。android:exported=”false”设置是否允许其他应用调用此服务</li>
<li>可以被其他进程复用，适用于为其他应用提供公共服务的Service。为系统常驻的Service，如天气服务</li>
<li>有独立进程，不受其他进程影响</li>
<li>具有更好的灵活性</li>
<li>占有的资源较多，需要使用AIDL等方式进行IPC</li>
</ol>
</blockquote>
<h3 id="1-2-3-startService-：不可交互的后台服务"><a href="#1-2-3-startService-：不可交互的后台服务" class="headerlink" title="1.2.3. startService()：不可交互的后台服务"></a>1.2.3. startService()：不可交互的后台服务</h3><blockquote>
<ol>
<li><p>定义一个类继承Service，重写onBind()方法，返回null即可。重写onStartCommand(Intent intent, int flags,int startId)执行任务</p>
</li>
<li><p>在Manifest清单文件中注册</p>
</li>
<li><p>使用Context.startService(Intent)启动服务</p>
</li>
<li><p>使用stopService(Intent)停止服务，或者调用Service的stopSelf()方法</p>
</li>
</ol>
</blockquote>
<p>onStartCommand(Intent intent, int flags,int startId)：</p>
<blockquote>
<ol>
<li>flag：服务的启动方式<ol>
<li>START_FLAG_REDELIVERY：如果你实现onStartCommand()来安排异步工作或者在另一个线程中工作, 那么你可能需要使用START_FLAG_REDELIVERY来让系统重新发送一个intent。这样如果你的服务在处理它的时候被Kill掉, Intent不会丢失. </li>
<li>START_FLAG_RETRY：表示服务之前被设为START_STICKY，则会被传入这个标记。<br>启动service的时候，onCreate方法只有第一次会调用，onStartCommand和onStart每次都被调用。onStartCommand会告诉系统如何重启服务，如判断是否异常终止后重新启动，在何种情况下异常终止.</li>
</ol>
</li>
<li>startId：用于表示此次Client执行startService(…)的请求请求标识，在多次startService(…)的情况下，呈现0,1,2….递增。可以用于stopSelf(id)</li>
<li>返回值：<ol>
<li>START_NOT_STICKY：“非粘性的”。如果在执行完onStartCommand后，服务被异常kill掉，系统不会自动重启该服务 </li>
<li>START_STICKY：如果service进程被kill掉，保留service的状态为开始状态，但不保留onStartCommand方法传入的intent对象。随后系统会尝试重新创建service，由于服务状态为开始状态，所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service，那么参数Intent将为null。 </li>
<li>START_REDELIVER_INTENT：重传Intent。使用这个返回值时，如果在执行完onStartCommand后，服务被异常kill掉，系统会自动重启该服务，重新执行onStartCommand，并将最后一次传入的Intent的值保留下来传入。</li>
<li>START_STICKY_COMPATIBILITY：START_STICKY的兼容版本，但不保证服务被kill后一定能重启。</li>
</ol>
</li>
</ol>
</blockquote>
<p>生命周期：</p>
<blockquote>
<p>onCreate()-&gt;onStartCommand() / onStart()（已过时）-&gt;onDestroy()</p>
</blockquote>
<ul>
<li><code>onCreate()</code>只调用一次，再次启动只会调用<code>onStartCommand()</code></li>
<li>服务一旦开启就跟开启者没有关系了，开启者退出，服务还在后台运行。</li>
<li>开启者不能调用服务的方法，可以使用broadcast通信，缺点是太重</li>
</ul>
<h3 id="1-2-4-bindService-：可交互的后台服务"><a href="#1-2-4-bindService-：可交互的后台服务" class="headerlink" title="1.2.4. bindService()：可交互的后台服务"></a>1.2.4. bindService()：可交互的后台服务</h3><blockquote>
<ol>
<li>定义一个类继承Service</li>
<li>定义一个内部类继承Binder，作用相当于服务的代理<ol>
<li>实现自定义接口方法提供对外。</li>
<li>也可以定义一个方法直接返回Service对象，如MyService.this，然后调用Service方法</li>
</ol>
</li>
<li>重写onBind()方法，返回一个Binder对象</li>
<li>在Manifest清单文件中注册</li>
<li>定义一个ServiceConnection对象，绑定/解绑服务会回调onServiceConnected（可以拿到IBinder对象，强制转换为自定义Binder接口）、onServiceDisconnected，</li>
<li>使用Context.bindService(Intent, ServiceConnection, int flags)启动服务<ol>
<li>flags:指定绑定是是否自动创建Service(如果Service还未创建)   0（不自动创建）或 BIND_AUTO_CREATE(自动创建)</li>
</ol>
</li>
<li>使用unbindService(ServiceConnection)停止服务</li>
</ol>
</blockquote>
<p>生命周期：</p>
<blockquote>
<p>onCreate()-&gt;onBind()-&gt;onUnbind()-&gt;onDestroy</p>
</blockquote>
<ul>
<li><code>onCreate()</code>只调用一次，不会调用<code>onStart()</code>或者<code>onStartCommand()</code>方法</li>
<li>生命周期和开启者绑定，开启者销毁，服务也会被销毁。如果有多个绑定者，则一个销毁，不会执行onUnbind方法</li>
<li>当没有任何client与Service绑定时，Service会自行销毁。</li>
<li>绑定者可以调用服务的方法</li>
<li>onServiceConnected返回的binder对象：<ul>
<li>如果不跨进程，返回的就是Service的onBind返回的对象。</li>
<li>如果跨进程，返回的是Service的代理对象</li>
</ul>
</li>
</ul>
<p><strong>注：BroadcastReceiver的Context不能用于绑定服务，因为广播生命周期较短。但可以在广播中startService()</strong></p>
<h3 id="1-2-5-前台服务"><a href="#1-2-5-前台服务" class="headerlink" title="1.2.5. 前台服务"></a>1.2.5. 前台服务</h3><p>由于后台服务优先级相对比较低，当系统出现内存不足的情况下，它就有可能会被回收掉，所以前台服务就是来弥补这个缺点的，它可以一直保持运行状态而不被系统回收。例如：在状态栏中的天气预报</p>
<blockquote>
<p>在Service的基础上创建一个Notification，然后使用Service的startForeground()方法即可启动为前台服务.</p>
</blockquote>
<h3 id="1-2-6-IntentService"><a href="#1-2-6-IntentService" class="headerlink" title="1.2.6. IntentService"></a>1.2.6. IntentService</h3><p>IntentService是专门用来解决Service中不能执行耗时操作这一问题的，创建一个IntentService也很简单，只要继承IntentService并覆写onHandlerIntent函数，在该函数中就可以执行耗时操作了。</p>
<blockquote>
<ol>
<li>默认直接实现了<code>onBind(Intent)</code>方法，直接返回null，并定义了抽象方法<code>onHandleIntent(Intent)</code>，用户自定义子类时，需要实现此方法；</li>
<li>默认实现了<code>onStartCommand</code>，并将Intent传递给<code>onHandleIntent</code></li>
<li>重写<code>onHandleIntent()</code>处理耗时任务，并且已经自动在新的线程中，用户无需自定义新线程；</li>
<li>子类需要重写默认的构造方法，且在构造方法中调用父类带参数的构造方法。设置子线程名称</li>
<li><code>onHandleIntent</code>执行完毕后，IntentService自动结束，无需手动停止服务</li>
<li>如果要重写其他生命周期，需要调用父类方法保证子线程能够正常启动</li>
<li>使用队列处理多个Intent，共用一个线程，不是多线程并发。</li>
</ol>
</blockquote>
<p><strong>如果要处理多线程并发，需要继承Service，然后在onStartCommand中创建子线程。每次startService都会开启一个子线程</strong></p>
<p>IntentService原理：使用Handler+HandlerThread实现单线程模型。Handler内部维护消息队列，多个Intent排队处理</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">IntentService</span> <span class="keyword">extends</span> <span class="title">Service</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> Looper mServiceLooper;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> ServiceHandler mServiceHandler;</span><br><span class="line">    <span class="keyword">private</span> String mName;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">boolean</span> mRedelivery;</span><br><span class="line"><span class="comment">//使用Handler+HandlerThread实现单线程模型。Handler内部维护消息队列，多个Intent排队处理</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">ServiceHandler</span> <span class="keyword">extends</span> <span class="title">Handler</span> </span>&#123;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">ServiceHandler</span><span class="params">(Looper looper)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">super</span>(looper);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">handleMessage</span><span class="params">(Message msg)</span> </span>&#123;</span><br><span class="line">            <span class="comment">//子线程执行，重写该方法</span></span><br><span class="line">            onHandleIntent((Intent)msg.obj);</span><br><span class="line">            <span class="comment">//终止服务</span></span><br><span class="line">            stopSelf(msg.arg1);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">IntentService</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>();</span><br><span class="line">        mName = name;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setIntentRedelivery</span><span class="params">(<span class="keyword">boolean</span> enabled)</span> </span>&#123;</span><br><span class="line">        mRedelivery = enabled;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate();</span><br><span class="line">        <span class="comment">//创建HandlerThread线程，继承Thread。</span></span><br><span class="line">        HandlerThread thread = <span class="keyword">new</span> HandlerThread(<span class="string">&quot;IntentService[&quot;</span> + mName + <span class="string">&quot;]&quot;</span>);</span><br><span class="line">        thread.start();</span><br><span class="line"></span><br><span class="line">        mServiceLooper = thread.getLooper();</span><br><span class="line">        mServiceHandler = <span class="keyword">new</span> ServiceHandler(mServiceLooper);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onStart</span><span class="params">(<span class="meta">@Nullable</span> Intent intent, <span class="keyword">int</span> startId)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//obtainMessage会创建一个message，并将target设置为this</span></span><br><span class="line">        Message msg = mServiceHandler.obtainMessage();</span><br><span class="line">        msg.arg1 = startId;</span><br><span class="line">        msg.obj = intent;</span><br><span class="line">        mServiceHandler.sendMessage(msg);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">onStartCommand</span><span class="params">(<span class="meta">@Nullable</span> Intent intent, <span class="keyword">int</span> flags, <span class="keyword">int</span> startId)</span> </span>&#123;</span><br><span class="line">        onStart(intent, startId);</span><br><span class="line">        <span class="keyword">return</span> mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        mServiceLooper.quit();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@Nullable</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> IBinder <span class="title">onBind</span><span class="params">(Intent intent)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@WorkerThread</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">onHandleIntent</span><span class="params">(<span class="meta">@Nullable</span> Intent intent)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="1-3-Broadcast：广播"><a href="#1-3-Broadcast：广播" class="headerlink" title="1.3. Broadcast：广播"></a>1.3. Broadcast：广播</h2><p>分为广播发送者和广播接收者。可用于进程或线程间通信。</p>
<p><strong>BroadcastReceiver的生命周期，从对象调用它开始，到onReceiver方法执行完成之后结束。每次广播被接收后会重新创建BroadcastReceiver对象，并在onReceiver方法中执行完就销毁，如果BroadcastReceiver的onReceiver方法中不能在10秒内执行完成，Android会出现ANR异常。所以不要在BroadcastReceiver的onReceiver方法中执行耗时的操作。</strong></p>
<p>原理：</p>
<ul>
<li>注册广播的时候，将BroadcastReceiver 和IntentFilter 封装到ReceiverRecord中，使用<code>HashMap&lt;String, ArrayList&lt;ReceiverRecord&gt;&gt;</code>进行记录，键是Action</li>
<li>注销的时候从Map移除</li>
<li>发送的时候通过Intent的action在Map中查找</li>
</ul>
<h3 id="1-3-1-广播分类"><a href="#1-3-1-广播分类" class="headerlink" title="1.3.1. 广播分类"></a>1.3.1. 广播分类</h3><ul>
<li><p>全局广播：发出的广播所有应用都可以接收，或者可以接收其他应用的广播。</p>
</li>
<li><p>本地广播：只能接收应用内部广播，发出的广播只有应用内部能接收。</p>
</li>
<li><p>静态广播：静态注册的广播，应用程序关闭后也能接收到广播</p>
</li>
<li><p>动态广播：动态注册的广播，与组件生命周期相同</p>
</li>
<li><p>无序广播/标准广播：所有的接收者都会接收事件，不可以被拦截，不可以被修改。</p>
</li>
<li><p>有序广播：按照优先级，一级一级的向下传递，接收者可以修改广播数据，也可以终止广播事件。</p>
</li>
</ul>
<h3 id="1-3-2-定义广播接收器"><a href="#1-3-2-定义广播接收器" class="headerlink" title="1.3.2. 定义广播接收器"></a>1.3.2. 定义广播接收器</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//自定义广播接收器</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyBroadCastReceiver</span> <span class="keyword">extends</span> <span class="title">BroadcastReceiver</span>   </span></span><br><span class="line"><span class="class"></span>&#123;  </span><br><span class="line">   <span class="meta">@Override</span>  </span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceive</span><span class="params">(Context context, Intent intent)</span>   </span></span><br><span class="line"><span class="function">   </span>&#123;   </span><br><span class="line">       <span class="comment">//可以从Intent中获取数据、还可以调用BroadcastReceiver的getResultData()获取数据</span></span><br><span class="line">       <span class="comment">//一般不进行耗时操作，不允许开启多线程</span></span><br><span class="line">   &#125;   </span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure>

<h3 id="1-3-3-注册广播接收器"><a href="#1-3-3-注册广播接收器" class="headerlink" title="1.3.3. 注册广播接收器"></a>1.3.3. 注册广播接收器</h3><p>可以注册监听系统广播（可能需要添加权限），下面例子用于监听自定义的广播</p>
<h4 id="静态注册"><a href="#静态注册" class="headerlink" title="静态注册"></a>静态注册</h4><ul>
<li>在Manifest中注册</li>
<li>常驻型广播：应用程序关闭后也能接收到广播</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">application</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">receiver</span> <span class="attr">android:name</span>=<span class="string">&quot;.MyBroadCastReceiver&quot;</span>&gt;</span>  </span><br><span class="line">		<span class="comment">&lt;!-- android:priority设置此接收者的优先级（从-1000到1000），用于有序广播，越大优先级越高 --&gt;</span></span><br><span class="line">		<span class="tag">&lt;<span class="name">intent-filter</span> <span class="attr">android:priority</span>=<span class="string">&quot;20&quot;</span>&gt;</span></span><br><span class="line">            <span class="comment">&lt;!-- 监听action为com.test.demo.broadcast的广播 --&gt;</span></span><br><span class="line">			<span class="tag">&lt;<span class="name">action</span> <span class="attr">android:name</span>=<span class="string">&quot;com.test.demo.broadcast&quot;</span>/&gt;</span></span><br><span class="line">		<span class="tag">&lt;/<span class="name">intent-filter</span>&gt;</span>  </span><br><span class="line">	<span class="tag">&lt;/<span class="name">receiver</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">application</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="动态注册"><a href="#动态注册" class="headerlink" title="动态注册"></a>动态注册</h4><ul>
<li>在java代码中注册</li>
<li>和所在的组件（Service、Activity、Application）的生命周期一致</li>
<li>需要在组件销毁的时候注销广播，<code>unregisterReceiver(recevier);</code>一般在相应的onDestroy方法中注销</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//实例化广播接收器</span></span><br><span class="line">MyBroadCastReceiver mBroadCastReceiver = <span class="keyword">new</span> MyBroadCastReceiver();</span><br><span class="line"><span class="comment">//实例化过滤器并设置要过滤出来的广播</span></span><br><span class="line">IntentFilter intentFilter = <span class="keyword">new</span> IntentFilter(<span class="string">&quot;com.test.demo.broadcast&quot;</span>);</span><br><span class="line"><span class="comment">//注册广播监听器</span></span><br><span class="line">myContext.registerReceiver(mBroadCastReceiver,intentFilter);</span><br></pre></td></tr></table></figure>

<h3 id="1-3-4-发送广播"><a href="#1-3-4-发送广播" class="headerlink" title="1.3.4. 发送广播"></a>1.3.4. 发送广播</h3><p>发送自定义广播。</p>
<h4 id="无序广播：所有的接收者都会接收事件，不可以被拦截，不可以被修改。"><a href="#无序广播：所有的接收者都会接收事件，不可以被拦截，不可以被修改。" class="headerlink" title="无序广播：所有的接收者都会接收事件，不可以被拦截，不可以被修改。"></a>无序广播：所有的接收者都会接收事件，不可以被拦截，不可以被修改。</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//定义action为com.test.demo.broadcast的意图，或者intent.setAction(&quot;com.test.demo.broadcast&quot;);</span></span><br><span class="line">Intent intent = <span class="keyword">new</span> Intent(<span class="string">&quot;com.test.demo.broadcast&quot;</span>);</span><br><span class="line"><span class="comment">//发送广播</span></span><br><span class="line">mContext.sendBroadcast(Intent);</span><br><span class="line"><span class="comment">//第二个参数是权限</span></span><br><span class="line">mContext.sendBroadcast(Intent, String);</span><br></pre></td></tr></table></figure>

<h4 id="有序广播：按照优先级，一级一级的向下传递，接收者可以修改广播数据，也可以终止广播事件。"><a href="#有序广播：按照优先级，一级一级的向下传递，接收者可以修改广播数据，也可以终止广播事件。" class="headerlink" title="有序广播：按照优先级，一级一级的向下传递，接收者可以修改广播数据，也可以终止广播事件。"></a>有序广播：按照优先级，一级一级的向下传递，接收者可以修改广播数据，也可以终止广播事件。</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//第一个参数：intent</span></span><br><span class="line"><span class="comment">//第二个参数：String类型的接收者权限</span></span><br><span class="line"><span class="comment">//第三个参数：BroadcastReceiver 指定的接收者</span></span><br><span class="line"><span class="comment">//第四个参数：Handler scheduler</span></span><br><span class="line"><span class="comment">//第五个参数：int 此次广播的标记 </span></span><br><span class="line"><span class="comment">//第六个参数：String 初始数据</span></span><br><span class="line"><span class="comment">//第七个参数：Bundle 往Intent中添加的额外数据</span></span><br><span class="line">mContext.sendOrderedBroadcast(Intent, String, BroadCastReceiver, Handler, <span class="keyword">int</span>, String, Bundle)；</span><br><span class="line"><span class="comment">//修改广播数据，下一级的广播使用getResultData获取数据</span></span><br><span class="line">setResultData();</span><br><span class="line"><span class="comment">//终止广播传递</span></span><br><span class="line">abortBroadcast();</span><br></pre></td></tr></table></figure>

<h3 id="1-3-5-本地广播"><a href="#1-3-5-本地广播" class="headerlink" title="1.3.5. 本地广播"></a>1.3.5. 本地广播</h3><ul>
<li>全局广播存在数据安全问题，使用本地广播可以与其他应用程序进行隔离，增强安全性</li>
<li>本地广播只能动态注册</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//使用LocalBroadcastManager类</span></span><br><span class="line"><span class="comment">//实例化本地广播</span></span><br><span class="line">LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(<span class="keyword">this</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//注册广播接收器</span></span><br><span class="line">localBroadcastManager.registerReceiver(recevier,intentFilter);</span><br><span class="line"><span class="comment">//注销广播接收器,localBroadcastManager同一个实例</span></span><br><span class="line">localBroadcastManager.unregisterReceiver()</span><br><span class="line">    </span><br><span class="line"><span class="comment">//发送无序广播</span></span><br><span class="line">localBroadcastManager.sendBroadcast(intent);</span><br><span class="line"><span class="comment">//发送有序广播</span></span><br><span class="line">localBroadcastManager.sendBroadcastSync(intent);</span><br></pre></td></tr></table></figure>

<h2 id="1-4-ContentProvider"><a href="#1-4-ContentProvider" class="headerlink" title="1.4. ContentProvider"></a>1.4. ContentProvider</h2><h1 id="2-其他"><a href="#2-其他" class="headerlink" title="2. 其他"></a>2. 其他</h1><h2 id="2-1-退出应用程序的方法"><a href="#2-1-退出应用程序的方法" class="headerlink" title="2.1. 退出应用程序的方法"></a>2.1. 退出应用程序的方法</h2><h3 id="2-1-1-按两下回退键退出应用："><a href="#2-1-1-按两下回退键退出应用：" class="headerlink" title="2.1.1. 按两下回退键退出应用："></a>2.1.1. 按两下回退键退出应用：</h3><ul>
<li>定义preTime属性</li>
<li>重写onKeyDown方法，判断点击了回退键</li>
<li>通过<code>System.currentTimeMillis();</code>方法获取当前时间</li>
<li><code>curTime-preTime&gt;2000</code>（2s）则弹出提示，并给preTime赋值，小于2s则退出程序</li>
</ul>
<h3 id="2-1-2-System-exit-0"><a href="#2-1-2-System-exit-0" class="headerlink" title="2.1.2. System.exit(0);"></a>2.1.2. System.exit(0);</h3><p>终止程序，终止当前运行的Java虚拟机。在部分机型会弹出应用程序崩溃，或者退出后再次启动</p>
<h3 id="2-1-3-抛出异常，强制退出"><a href="#2-1-3-抛出异常，强制退出" class="headerlink" title="2.1.3. 抛出异常，强制退出"></a>2.1.3. 抛出异常，强制退出</h3><h3 id="2-1-4-使用Application退出：自行维护Activity列表"><a href="#2-1-4-使用Application退出：自行维护Activity列表" class="headerlink" title="2.1.4. 使用Application退出：自行维护Activity列表"></a>2.1.4. 使用Application退出：自行维护Activity列表</h3><ul>
<li>自定义Application，创建一个<code>List&lt;Activity&gt;</code>列表，用于存放启动的Activity</li>
<li>并且分别定义<code>addActivity、removeActivity、removeAllActivity</code>方法</li>
<li>定义BaseActivity，重写onCreate方法，获取Application，每次创建新的Activity的时候调用addActivity方法</li>
<li>销毁Activity的时候调用Application的removeActivity方法</li>
<li>需要退出整个应用的时候调用removeAllActivity方法</li>
</ul>
<p>注：自定义Application需要在Manifest中注册</p>
<h3 id="2-1-5-使用广播退出"><a href="#2-1-5-使用广播退出" class="headerlink" title="2.1.5. 使用广播退出"></a>2.1.5. 使用广播退出</h3><ul>
<li>定义BaseActivity，重写onCreate和onDestroy方法，分别注册和注销广播，设置IntentFilter过滤广播意图</li>
<li>定义BroadcastReceiver，重写onReceive方法，接收到广播之后判断内容，然后<code>finish();</code>销毁Activity</li>
<li>需要退出程序的时候发送广播sendBroadcast(intent);</li>
</ul>
<p>所有的Activity都注册了广播，共用一个广播接收器，分别finish();</p>
<h2 id="2-2-Android-Context上下文"><a href="#2-2-Android-Context上下文" class="headerlink" title="2.2. Android Context上下文"></a>2.2. Android Context上下文</h2><h2 id="2-3-Dalvik虚拟机进程"><a href="#2-3-Dalvik虚拟机进程" class="headerlink" title="2.3. Dalvik虚拟机进程"></a>2.3. Dalvik虚拟机进程</h2><p>一个运行中的dalvik虚拟机实例占有一个进程，默认情况下一个应用程序的所有组件在同一个进程中。</p>
<p>也有可能在不同进程中：通过在manifest中用process属性指定组件所运行的进程的名字。进程名称前面需要加冒号:</p>
<h2 id="2-4-SpanableString：Text装饰"><a href="#2-4-SpanableString：Text装饰" class="headerlink" title="2.4. SpanableString：Text装饰"></a>2.4. SpanableString：Text装饰</h2><p>SpannableString可以用来装饰String，如把String的某一部分加上下划线，粗体，加上图片，添加点击事件等</p>
<p>SpanableString和SpannableStringBuilder：相当于String和StringBuilder的关系</p>
<p>用法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//what：包括各种各样的Span</span></span><br><span class="line"><span class="comment">//start、end：字符串开始和结束位置</span></span><br><span class="line"><span class="comment">/* Flag：start和end是开区间还是闭区间</span></span><br><span class="line"><span class="comment">Spanned.SPAN_EXCLUSIVE_EXCLUSIVE —— (a,b)</span></span><br><span class="line"><span class="comment">Spanned.SPAN_EXCLUSIVE_INCLUSIVE —— (a,b]</span></span><br><span class="line"><span class="comment">Spanned.SPAN_INCLUSIVE_EXCLUSIVE —— [a,b)</span></span><br><span class="line"><span class="comment">Spanned.SPAN_INCLUSIVE_INCLUSIVE —— [a,b]</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSpan</span><span class="params">(Object what, <span class="keyword">int</span> start, <span class="keyword">int</span> end, <span class="keyword">int</span> flags)</span> </span>&#123;&#125;</span><br></pre></td></tr></table></figure>

<p>常用的Span：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">BackgroundColorSpan : 文本背景色</span><br><span class="line">ForegroundColorSpan : 文本颜色</span><br><span class="line">MaskFilterSpan : 修饰效果，如模糊(BlurMaskFilter)浮雕</span><br><span class="line">RasterizerSpan : 光栅效果</span><br><span class="line">StrikethroughSpan : 删除线</span><br><span class="line">SuggestionSpan : 相当于占位符</span><br><span class="line">UnderlineSpan : 下划线</span><br><span class="line">AbsoluteSizeSpan : 文本字体（绝对大小）</span><br><span class="line">DynamicDrawableSpan : 设置图片，基于文本基线或底部对齐。</span><br><span class="line">ImageSpan : 图片</span><br><span class="line">RelativeSizeSpan : 相对大小（文本字体）</span><br><span class="line">ScaleXSpan : 基于x轴缩放</span><br><span class="line">StyleSpan : 字体样式：粗体、斜体等</span><br><span class="line">SubscriptSpan : 下标（数学公式会用到）</span><br><span class="line">SuperscriptSpan : 上标（数学公式会用到）</span><br><span class="line">TextAppearanceSpan : 文本外貌（包括字体、大小、样式和颜色）</span><br><span class="line">TypefaceSpan : 文本字体</span><br><span class="line">URLSpan : 文本超链接</span><br><span class="line">ClickableSpan : 点击事件</span><br></pre></td></tr></table></figure>



<h2 id="2-5-Notification：通知"><a href="#2-5-Notification：通知" class="headerlink" title="2.5. Notification：通知"></a>2.5. Notification：通知</h2><h2 id="2-6-进程分类和优先级"><a href="#2-6-进程分类和优先级" class="headerlink" title="2.6. 进程分类和优先级"></a>2.6. 进程分类和优先级</h2><p><strong>前台进程&gt;可见进程&gt;服务进程&gt;后台进程&gt;空进程</strong></p>
<h3 id="2-6-1-前台进程"><a href="#2-6-1-前台进程" class="headerlink" title="2.6.1. 前台进程"></a>2.6.1. 前台进程</h3><p>前台进程是目前正在屏幕上显示的进程和一些系统进程，也就是和用户正在交互的进程。</p>
<p>通常，在任何时间点，只有很少的前台进程存在。它们只有在达到无法调合的矛盾时才会被杀－－如内存太小而不能继续运行时。通常，到了这时，设备就达到了一个内存分页调度状态，所以需要杀一些前台进程来保证用户界面的反应</p>
<p>具体情况：</p>
<ul>
<li>这个进程拥有一个正在与用户交互的Activity(这个Activity的onResume()方法被调用)。</li>
<li>这个进程拥有一个绑定到正在与用户交互的activity上的Service。</li>
<li>这个进程拥有一个前台运行的Service（在service中调用<code>startForeground(id,notification)</code>创建前台服务）。</li>
<li>这个进程拥有一个正在执行其任何一个生命周期回调方法（onCreate(),onStartCommand(),onDestroy()）的Service。</li>
<li>这个进程拥有正在执行其onReceive()方法的BroadcastReceiver。</li>
</ul>
<h3 id="2-6-2-可见进程"><a href="#2-6-2-可见进程" class="headerlink" title="2.6.2. 可见进程"></a>2.6.2. 可见进程</h3><p>一个进程不拥有运行于前台的组件，但是依然能影响用户所见。</p>
<p>具体情况：</p>
<ul>
<li>这个进程拥有一个不在前台但仍可见的Activity(它的onPause()方法被调用)。<ul>
<li>如一个前台activity启动一个对话框。</li>
</ul>
</li>
</ul>
<h3 id="2-6-3-服务进程"><a href="#2-6-3-服务进程" class="headerlink" title="2.6.3. 服务进程"></a>2.6.3. 服务进程</h3><p>通过 startService() 方法启动的进程，但不属于前台进程和可见进程。</p>
<p>尽管一个服务进程不直接影响用户所见，但是它们通常做一些用户关心的事情（比如播放音乐或下载数据），所以系统不到前台进程和可见进程活不下去时不会杀它。</p>
<h3 id="2-6-4-后台进程"><a href="#2-6-4-后台进程" class="headerlink" title="2.6.4. 后台进程"></a>2.6.4. 后台进程</h3><p>一个进程拥有一个当前不可见的activity(activity的onStop()方法被调用)。</p>
<p>这样的进程不会直接影响到用户体验，所以系统可以在任意时刻杀了它们从而为前台、可见、以及服务进程们提供存储空间。通常有很多后台进程在运行。它们被保存在一个LRU(最近最少使用)列表中来确保拥有最近刚被看到的activity的进程最后被杀。如果一个activity正确的实现了它的生命周期方法，并保存了它的当前状态，那么杀死它的进程将不会对用户的可视化体验造成影响。因为当用户返回到这个activity时，这个activity会恢复它所有的可见状态。</p>
<h3 id="2-6-5-空进程"><a href="#2-6-5-空进程" class="headerlink" title="2.6.5. 空进程"></a>2.6.5. 空进程</h3><p>空进程指的是在这些进程内部，没有任何东西在运行。保留这种进程的的唯一目的是用作缓存，以缩短该应用下次在其中运行组件所需的启动时间。</p>
<p>系统经常为了平衡在进程高速缓存和底层的内核高速缓存之间的整体系统资源而杀死它们。</p>
<h2 id="2-7-Android介绍"><a href="#2-7-Android介绍" class="headerlink" title="2.7. Android介绍"></a>2.7. Android介绍</h2><h3 id="2-7-1-系统架构"><a href="#2-7-1-系统架构" class="headerlink" title="2.7.1. 系统架构"></a>2.7.1. 系统架构</h3><p><img src="/images/Review/Android%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84.jpg" alt="Android系统架构"></p>
<h3 id="2-7-2-历史版本"><a href="#2-7-2-历史版本" class="headerlink" title="2.7.2. 历史版本"></a>2.7.2. 历史版本</h3><table>
<thead>
<tr>
<th>Android版本名称Code name</th>
<th>Android版本</th>
<th>版本发布时间</th>
<th>对应API</th>
</tr>
</thead>
<tbody><tr>
<td>(no code name)</td>
<td>1.0</td>
<td>2008年9月23日</td>
<td>API level 1</td>
</tr>
<tr>
<td>(no code name)</td>
<td>1.1</td>
<td>2009年2月2日</td>
<td>API level 2</td>
</tr>
<tr>
<td>Cupcake（仙女蛋糕）</td>
<td>1.5</td>
<td>2009年4月17日</td>
<td>API level 3,NDK 1</td>
</tr>
<tr>
<td>Donut（甜甜圈）</td>
<td>1.6</td>
<td>2009年9月15日</td>
<td>API level 4,NDK 2</td>
</tr>
<tr>
<td>Eclair（闪电泡芙）</td>
<td>2.0.1</td>
<td>2009年12月3日</td>
<td>API level 6</td>
</tr>
<tr>
<td>Eclair（闪电泡芙）</td>
<td>2.1</td>
<td>2010年1月12日</td>
<td>API level 7,NDK3</td>
</tr>
<tr>
<td>Froyo（冻酸奶）</td>
<td>2.2.x</td>
<td>2010年1月12日</td>
<td>API level 8,NDK 4</td>
</tr>
<tr>
<td>Gingerbread（姜饼）</td>
<td>2.3-2.3.2</td>
<td>2011年1月1日</td>
<td>API level 9,NDK5</td>
</tr>
<tr>
<td>Gingerbread（姜饼）</td>
<td>2.3.3-2.3.7</td>
<td>2011年9月2日</td>
<td>API level 10</td>
</tr>
<tr>
<td>Honeycomb（蜂巢）</td>
<td>3.0</td>
<td>2011年2月24日</td>
<td>API level 11</td>
</tr>
<tr>
<td>Honeycomb（蜂巢）</td>
<td>3.1</td>
<td>2011年5月10日</td>
<td>API level 12,NDK 6</td>
</tr>
<tr>
<td>Honeycomb（蜂巢）</td>
<td>3.2.x</td>
<td>2011年7月15日</td>
<td>API level 13</td>
</tr>
<tr>
<td>Ice Cream Sandwich（冰淇淋三明治）</td>
<td>4.0.1-4.0.2</td>
<td>2011年10月19日</td>
<td>API level 14,NDK 7</td>
</tr>
<tr>
<td>Ice Cream Sandwich（冰淇淋三明治）</td>
<td>4.0.3-4.0.4</td>
<td>2012年2月6日</td>
<td>API level 15,NDK 8</td>
</tr>
<tr>
<td>Jelly Bean（彩虹糖）</td>
<td>4.1</td>
<td>2012年6月28日</td>
<td>API level 16</td>
</tr>
<tr>
<td>Jelly Bean（彩虹糖）</td>
<td>4.1.1</td>
<td>2012年6月28日</td>
<td>API level 16</td>
</tr>
<tr>
<td>Jelly Bean（彩虹糖）</td>
<td>4.2-4.2.2</td>
<td>2012年11月</td>
<td>API level 17</td>
</tr>
<tr>
<td>Jelly Bean（彩虹糖）</td>
<td>4.3</td>
<td>2013年7月</td>
<td>API level 18</td>
</tr>
<tr>
<td>KitKat（奇巧，巧克力饼干）</td>
<td>4.4</td>
<td>2013年7月24日</td>
<td>API level 19</td>
</tr>
<tr>
<td>Kitkat Watch（奇巧巧克力-穿戴设备）</td>
<td>4.4W</td>
<td>2014年6月</td>
<td>API level 20</td>
</tr>
<tr>
<td>Lollipop(Android L)（棒棒糖）</td>
<td>5.0</td>
<td>2014年6月25日</td>
<td>API level 21</td>
</tr>
<tr>
<td>Lollipop(Android L)（棒棒糖）</td>
<td>5.1</td>
<td>2014年6月25日</td>
<td>API level 22</td>
</tr>
<tr>
<td>Marshmallow(Android M)（棉花糖）</td>
<td>6.0</td>
<td>2015年5月28日</td>
<td>API level 23</td>
</tr>
<tr>
<td>Nougat(Android N)（牛轧糖）</td>
<td>7.0</td>
<td>2016年5月18日</td>
<td>API level 24</td>
</tr>
<tr>
<td>Nougat(Android N)（牛轧糖）</td>
<td>7.1</td>
<td>2016年12月</td>
<td>API level 25</td>
</tr>
<tr>
<td>Oreo（Android O）（奥利奥）</td>
<td>8.0</td>
<td>2017年8月22日</td>
<td>API level 26</td>
</tr>
<tr>
<td>Oreo（Android O）（奥利奥）</td>
<td>8.1</td>
<td>2017年12月5日</td>
<td>API level 27</td>
</tr>
<tr>
<td>Pie （Android P）（馅饼）</td>
<td>9.0</td>
<td>2018年8月7日</td>
<td>API level 28</td>
</tr>
</tbody></table>
<h3 id="2-7-3-打包流程"><a href="#2-7-3-打包流程" class="headerlink" title="2.7.3. 打包流程"></a>2.7.3. 打包流程</h3><p><img src="/images/Review/Android%E6%89%93%E5%8C%85%E6%B5%81%E7%A8%8B.jpg" alt="Android打包流程"></p>
<h1 id="3-自定义View"><a href="#3-自定义View" class="headerlink" title="3. 自定义View"></a>3. 自定义View</h1><h2 id="3-1-绘制过程"><a href="#3-1-绘制过程" class="headerlink" title="3.1. 绘制过程"></a>3.1. 绘制过程</h2><p>重写onMeasure()-&gt;onLayout()-&gt;onDraw()</p>
<h2 id="3-2-控制绘制顺序"><a href="#3-2-控制绘制顺序" class="headerlink" title="3.2. 控制绘制顺序"></a>3.2. 控制绘制顺序</h2><p>图片来源于HenCoder大佬的教程，自定义View讲的很详细很清楚：<a target="_blank" rel="noopener" href="https://hencoder.com/ui-1-5/">HenCoder Android 开发进阶：自定义 View 1-5 绘制顺序</a></p>
<p><img src="/images/Review/%E8%87%AA%E5%AE%9A%E4%B9%89View%E7%BB%98%E5%88%B6%E9%A1%BA%E5%BA%8F.jpg" alt="自定义View绘制顺序"></p>
<h1 id="4-事件分发"><a href="#4-事件分发" class="headerlink" title="4. 事件分发"></a>4. 事件分发</h1><h1 id="5-动画"><a href="#5-动画" class="headerlink" title="5. 动画"></a>5. 动画</h1><h2 id="5-1-帧动画"><a href="#5-1-帧动画" class="headerlink" title="5.1. 帧动画"></a>5.1. 帧动画</h2><p>主要使用AnimationDrawable，Drawable的子类，可以通过Java代码或者xml文件创建Drawable</p>
<p>xml创建：位于drawable目录下，可以当作普通的drawable使用</p>
<ul>
<li><code>&lt;animation-list&gt;</code>：图片集合，<code>android:oneshot</code>属性：执行一次</li>
<li><code>&lt;item&gt;</code>：<code>android:duration、android:drawable </code>属性</li>
</ul>
<p>Drawable强制转换为AnimationDrawable类型，然后调用AnimationDrawable.start()方法播放</p>
<p>注：不能在onCreate方法中调用，因为AnimationDrawable还未完全附着到window上，可以在onWindowFocusChanged()方法中调用。</p>
<h2 id="5-2-补间动画（视图动画）"><a href="#5-2-补间动画（视图动画）" class="headerlink" title="5.2. 补间动画（视图动画）"></a>5.2. 补间动画（视图动画）</h2><ul>
<li><p>Java代码创建：</p>
<ul>
<li>TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnimation：平移、旋转、缩放、透明</li>
<li>AnimationSet：动画集合</li>
</ul>
</li>
<li><p>xml创建：</p>
<ul>
<li><code>&lt;translate&gt;、&lt;scale&gt;、&lt;rotate&gt;、&lt;alpha&gt;、&lt;set&gt;</code>标签</li>
<li>通过AnimationUtils.loadAnimation(this, R.anim.***);加载，返回Animation对象。</li>
</ul>
</li>
<li><p>view.startAnimation()播放，或者anim.start();</p>
</li>
<li><p>animation.setAnimationListener()设置动画监听</p>
</li>
<li><p>进阶：插值器Interplolator</p>
</li>
</ul>
<p>注：补间动画无不会改变view位置和大小等属性，如点击移动后的位置无法响应事件。</p>
<h2 id="5-3-属性动画（3-0以上，API-11）"><a href="#5-3-属性动画（3-0以上，API-11）" class="headerlink" title="5.3. 属性动画（3.0以上，API 11）"></a>5.3. 属性动画（3.0以上，API 11）</h2><ul>
<li><p>ObjectAnimator、ValueAnimator……</p>
<ul>
<li>```java<br>//参数：view、动画、开始值、结束值<br>ObjectAnimator mObjectAnimator= ObjectAnimator.ofInt(view, “rotationY”, 0,  1).setDuration(2000);<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">* AnimatorSet：动画集合</span><br><span class="line"></span><br><span class="line">* Interplotator：插值器，控制动画速率</span><br><span class="line"></span><br><span class="line">* Evaluator：估值器，根据起始值、结束值和插值计算当前属性值、</span><br><span class="line"></span><br><span class="line"># 6. 进程间通信</span><br><span class="line"></span><br><span class="line">## 6.1. AIDL</span><br><span class="line"></span><br><span class="line">## 6.2. Messenger</span><br><span class="line"></span><br><span class="line">## 6.3. Broadcast</span><br><span class="line"></span><br><span class="line">## 6.4. Intent</span><br><span class="line"></span><br><span class="line">## 6.5. ContentProvider</span><br><span class="line"></span><br><span class="line"># 7. 线程间通信</span><br><span class="line"></span><br><span class="line">## 7.1. Handler</span><br><span class="line"></span><br><span class="line">### 7.1.1. ThreadLocal：线程本地变量</span><br><span class="line"></span><br><span class="line">每个线程各自拥有，互不影响。get到的值是不一样的</span><br><span class="line"></span><br><span class="line">### 7.1.2. Handler机制（占个坑，有空补图）</span><br><span class="line"></span><br><span class="line">Handler：Looper（通过Looper.myLooper()从ThreadLocal中获取）、MessageQueue（Looper中获取）。</span><br><span class="line"></span><br><span class="line">Handler构造方法：</span><br><span class="line"></span><br><span class="line">* new Handler()：会从ThreadLocal中获取</span><br><span class="line">* new Handler(Looper)：使用外部传递的Looper，配合HandlerThread使用，HandlerThread开启新线程，创建Looper对象，Looper循环会在HandlerThread中执行，即Handler的handleMessage会在HandlerThread中执行</span><br><span class="line"></span><br><span class="line">MessageQueue：Message（使用单链表的形式，存储next Message），next()方法可以获取Message，没有消息则阻塞，底层使用native方法，mQuitAllowed（是否允许退出：prepareMainLooper()中设置为false，主线程不允许，prepare为true）</span><br><span class="line"></span><br><span class="line">Message：next（存储next Message），what（消息code），obj（消息内容），target（消息的目标：Handler）</span><br><span class="line"></span><br><span class="line">Looper：MessageQueue，&#96;sThreadLocal&#x3D; new ThreadLocal&lt;Looper&gt;()&#96;（线程本地变量），Thread（Looper所在的线程，直接赋值为Thread.currentThread()），静态方法prepare()（ThreadLocal.set(new Looper())，创建自身，并设置到ThreadLocal中），静态方法loop()（不断从MessageQueue中获取消息，死循环，通过target对象执行handleMessage方法，在loop所在线程），静态方法myLooper()（ThreadLocal.get()获取当前线程的Looper），quit()终止循环（移除所有消息），quitSafely（移除延时消息，可以让已经在队列的消息执行完毕，共同点：不再接收消息）。静态方法getMainLooper()（保存了mainLooper对象，任何地方都能获取到主线程的Looper），</span><br><span class="line"></span><br><span class="line">HandlerThread：继承Thread，在子线程中创建了Looper对象（prepare），并执行loop循环，即handleMessage在子线程</span><br><span class="line"></span><br><span class="line">HandlerThread特点：</span><br><span class="line"></span><br><span class="line">* 继承Thread，内部建立了Looper，并执行Looper循环，避免了手动维护Looper</span><br><span class="line">* HandlerThread将loop转到子线程中处理，分担MainLooper的工作量，降低了主线程的压力，使主界面更流畅。</span><br><span class="line">* 开启一个线程起到多个线程的作用。处理任务是串行执行，按消息发送顺序进行处理。HandlerThread本质是单线程，而不是并发，在线程内部，代码是串行处理的。</span><br><span class="line">* 由于每一个任务都将以队列的方式逐个被执行到，一旦队列中有某个任务执行时间过长，那么就会导致后续的任务都会被延迟处理。</span><br><span class="line">* 拥有自己的消息队列，它不会干扰或阻塞UI线程。</span><br><span class="line">* 网络IO操作，HandlerThread并不适合，因为它只有一个线程，还得排队一个一个等着。</span><br><span class="line"></span><br><span class="line">总结：</span><br><span class="line"></span><br><span class="line">* Handler的Looper是在主线程，一般用法是在子线程sendMessage，然后在主线程handleMessage</span><br><span class="line">* HandlerThread的Looper在子线程，即handleMessage在子线程</span><br><span class="line"></span><br><span class="line">基本使用：</span><br><span class="line"></span><br><span class="line">&#96;&#96;&#96;java</span><br><span class="line">HandlerThread thread &#x3D; new HandlerThread(threadName);&#x2F;&#x2F;创建线程</span><br><span class="line">mHandlerThread.start();&#x2F;&#x2F;启动线程</span><br><span class="line">Handler handler &#x3D; new Handler(thread.getLooper())&#123;&#x2F;&#x2F;传入子线程的Looper，</span><br><span class="line">    &#x2F;&#x2F;如果线程还没启动或者Looper还没创建，getLooper会wait阻塞，在run中创建完后，会notifyAll</span><br><span class="line">    @Override</span><br><span class="line">	public void handleMessage(Message msg)</span><br><span class="line">    &#123;</span><br><span class="line">		&#x2F;&#x2F;doSomething   </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>
<p>HandlerThread关键代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">	mTid = Process.myTid();</span><br><span class="line">	Looper.prepare();</span><br><span class="line">	<span class="keyword">synchronized</span> (<span class="keyword">this</span>) &#123;</span><br><span class="line">		mLooper = Looper.myLooper();</span><br><span class="line">		notifyAll();<span class="comment">//唤醒</span></span><br><span class="line">    &#125;</span><br><span class="line">	Process.setThreadPriority(mPriority);</span><br><span class="line">	onLooperPrepared();</span><br><span class="line">	Looper.loop();</span><br><span class="line">	mTid = -<span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> Looper <span class="title">getLooper</span><span class="params">()</span> </span>&#123;</span><br><span class="line">	<span class="keyword">if</span> (!isAlive()) &#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">	&#125;</span><br><span class="line"><span class="comment">// If the thread has been started, wait until the looper has been created.</span></span><br><span class="line">	<span class="keyword">synchronized</span> (<span class="keyword">this</span>) &#123;</span><br><span class="line">		<span class="keyword">while</span> (isAlive() &amp;&amp; mLooper == <span class="keyword">null</span>) &#123;</span><br><span class="line">			<span class="keyword">try</span> &#123;</span><br><span class="line">				wait();<span class="comment">//阻塞</span></span><br><span class="line">			&#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> mLooper;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="7-2-AsyncTask"><a href="#7-2-AsyncTask" class="headerlink" title="7.2. AsyncTask"></a>7.2. AsyncTask</h2><h2 id="7-3-EventBus"><a href="#7-3-EventBus" class="headerlink" title="7.3. EventBus"></a>7.3. EventBus</h2><h1 id="8-Intent"><a href="#8-Intent" class="headerlink" title="8. Intent"></a>8. Intent</h1><p>Intent是一种在不同组件之间传递的请求消息，是应用程序发出的请求和意图。作为一个完整的消息传递机制，Intent不仅需要发送端，还需要接收端。</p>
<h3 id="2-9-1-显式Intent"><a href="#2-9-1-显式Intent" class="headerlink" title="2.9.1. 显式Intent"></a>2.9.1. 显式Intent</h3><p>明确指出了组件名称</p>
<blockquote>
<p>一般用于应用程序内部传递消息（因为我们无法知道其他应用程序的组件名称）</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Intent intent=<span class="keyword">new</span> Intent(MainActivity.<span class="keyword">this</span>,SecondActivity.class);</span><br><span class="line">startActivity(intent);</span><br></pre></td></tr></table></figure>

<h3 id="2-9-2-隐式Intent"><a href="#2-9-2-隐式Intent" class="headerlink" title="2.9.2. 隐式Intent"></a>2.9.2. 隐式Intent</h3><p>通过使用IntentFilter，由系统（AMS）来找到对应的组件。</p>
<blockquote>
<p>在Manifest文件中声明Intent-Filter。包括Action、Category、Data。</p>
<p>Extra和Flag在解析Intent找到组件时是不起作用的</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//过滤出电话程序</span></span><br><span class="line">Intent intent = <span class="keyword">new</span> Intent(Intent.ACTION_CALL);</span><br><span class="line">intent.setData(Uri.parse(<span class="string">&quot;tel:10086&quot;</span>));</span><br><span class="line">startActivity(intent);</span><br><span class="line"><span class="comment">//打开浏览器，并访问网址</span></span><br><span class="line">Intent intent = <span class="keyword">new</span> Intent(Intent.ACTION_VIEW,Uri.parse(<span class="string">&quot;http://www.baidu.com&quot;</span>));</span><br><span class="line">startActivity(intent);</span><br></pre></td></tr></table></figure>

<p>常用Action</p>
<table>
<thead>
<tr>
<th>动作</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>ACTION_PICK</td>
<td>启动一个子Activity，从提供的数据列表中选取一项</td>
</tr>
<tr>
<td>ACTION_SEARCH</td>
<td>启动一个Activity，执行搜索动作</td>
</tr>
<tr>
<td>ACTION_SENDTO</td>
<td>启动一个Activity，向数据提供的联系人发送信息</td>
</tr>
<tr>
<td>ACTION_SEND</td>
<td>启动一个可以发送数据的Activity，短信</td>
</tr>
<tr>
<td>ACTION_VIEW</td>
<td>最常用的动作，对以Uri方式传送的数据，根据Uri协议部分以最佳方式启动相应的Activity进行处理。对于http:address将打开浏览器查看；对于tel:address将打开拨号界面并呼叫指定的电话号码</td>
</tr>
<tr>
<td>ACTION_WEB_SEARCH</td>
<td>打开一个Activity，对提供的数据进行Web搜索</td>
</tr>
<tr>
<td>ACTION_ANSWER</td>
<td>打开接听电话的Activity，默认为Android内置的拨号界面</td>
</tr>
<tr>
<td>ACTION_CALL</td>
<td>打开拨号盘界面并拨打电话，使用Uri中的数字部分作为电话号码</td>
</tr>
<tr>
<td>ACTION_DIAL</td>
<td>打开内置拨号界面，显示Uri中提供的电话号码</td>
</tr>
<tr>
<td>ACTION_EDIT</td>
<td>打开一个Activity，对所提供的数据进行编辑操作</td>
</tr>
<tr>
<td>ACTION_DELETE</td>
<td>打开一个Activity，对所提供的数据进行删除操作</td>
</tr>
<tr>
<td>ACTION_INSERT</td>
<td>打开一个Activity，在提供数据的当前位置插入新项</td>
</tr>
</tbody></table>
<h1 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h1><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/fenggering/article/details/53907654">Android onSaveInstanceState()和onRestoreInstanceState()调用时机</a></p>
<p><a target="_blank" rel="noopener" href="https://www.jianshu.com/p/ea5e233d9f43">Android 两种注册、发送广播的区别</a></p>

    </div>

    
    
    
        

  <div class="followme">
    <p>欢迎关注我的其它发布渠道</p>

    <div class="social-list">

        <div class="social-item">
          <a target="_blank" class="social-link" href="/images/wechat_channel.jpg">
            <span class="icon">
              <i class="fab fa-weixin"></i>
            </span>

            <span class="label">WeChat</span>
          </a>
        </div>
    </div>
  </div>


      <footer class="post-footer">
          
          <div class="post-tags">
              <a href="/" rel="tag"><i class="fa fa-tag"></i> </a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/01/14/java-2019-1-14-JavaReflection/" rel="prev" title="java反射">
      <i class="fa fa-chevron-left"></i> java反射
    </a></div>
      <div class="post-nav-item">
    <a href="/2019/02/14/java-2019-2-14-JavaAnnontation/" rel="next" title="java注解（更新中）">
      java注解（更新中） <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="header-overlay"></div>
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#1-%E5%9B%9B%E5%A4%A7%E7%BB%84%E4%BB%B6"><span class="nav-number">1.</span> <span class="nav-text">1. 四大组件</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-1-Activity%EF%BC%9A%E6%B4%BB%E5%8A%A8"><span class="nav-number">1.1.</span> <span class="nav-text">1.1. Activity：活动</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-1-%E5%9B%9B%E4%B8%AA%E7%8A%B6%E6%80%81"><span class="nav-number">1.1.1.</span> <span class="nav-text">1.1.1. 四个状态</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-2-%E4%B8%83%E5%A4%A7%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">1.1.2.</span> <span class="nav-text">1.1.2. 七大生命周期</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#onSavedInstanceState%EF%BC%9A%E9%80%9A%E8%BF%87Bundle%EF%BC%88key-value%EF%BC%89%E4%BF%9D%E5%AD%98Activity%E7%9A%84%E5%AE%9E%E4%BE%8B%EF%BC%8C%E7%94%A8%E4%BA%8E%E6%81%A2%E5%A4%8D%E9%A1%B5%E9%9D%A2%E6%84%8F%E5%A4%96%E9%94%80%E6%AF%81%E5%89%8D%E7%9A%84%E7%8A%B6%E6%80%81"><span class="nav-number">1.1.2.1.</span> <span class="nav-text">onSavedInstanceState：通过Bundle（key-value）保存Activity的实例，用于恢复页面意外销毁前的状态</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#onRestoreInstanceState%EF%BC%9A%E8%8E%B7%E5%8F%96onSavedInstanceState%E4%BF%9D%E5%AD%98%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E6%81%A2%E5%A4%8D%E9%A1%B5%E9%9D%A2%E7%8A%B6%E6%80%81"><span class="nav-number">1.1.2.2.</span> <span class="nav-text">onRestoreInstanceState：获取onSavedInstanceState保存的数据，恢复页面状态</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%A8%AA%E7%AB%96%E5%B1%8F%E5%88%87%E6%8D%A2"><span class="nav-number">1.1.2.3.</span> <span class="nav-text">横竖屏切换</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-3-%E5%9B%9B%E7%A7%8D%E5%90%AF%E5%8A%A8%E6%96%B9%E5%BC%8F%EF%BC%88LaunchMode%EF%BC%89"><span class="nav-number">1.1.3.</span> <span class="nav-text">1.1.3. 四种启动方式（LaunchMode）</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#standard%E6%A8%A1%E5%BC%8F"><span class="nav-number">1.1.3.1.</span> <span class="nav-text">standard模式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#singleTop%E6%A8%A1%E5%BC%8F%EF%BC%9A%E6%A0%88%E9%A1%B6%E5%A4%8D%E7%94%A8"><span class="nav-number">1.1.3.2.</span> <span class="nav-text">singleTop模式：栈顶复用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#singleTask%E6%A8%A1%E5%BC%8F%EF%BC%9A%E6%A0%88%E5%86%85%E5%A4%8D%E7%94%A8"><span class="nav-number">1.1.3.3.</span> <span class="nav-text">singleTask模式：栈内复用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#singleInstance%E6%A8%A1%E5%BC%8F"><span class="nav-number">1.1.3.4.</span> <span class="nav-text">singleInstance模式</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-4-taskAffinity%E5%B1%9E%E6%80%A7"><span class="nav-number">1.1.4.</span> <span class="nav-text">1.1.4. taskAffinity属性</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-5-Intent%E7%9A%84Flag%E5%B1%9E%E6%80%A7"><span class="nav-number">1.1.5.</span> <span class="nav-text">1.1.5. Intent的Flag属性</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-2-Service%EF%BC%9A%E6%9C%8D%E5%8A%A1"><span class="nav-number">1.2.</span> <span class="nav-text">1.2. Service：服务</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-1-Service%E5%92%8CThread%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-number">1.2.1.</span> <span class="nav-text">1.2.1. Service和Thread的区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-2-%E6%9C%AC%E5%9C%B0%E6%9C%8D%E5%8A%A1%E5%92%8C%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1"><span class="nav-number">1.2.2.</span> <span class="nav-text">1.2.2. 本地服务和远程服务</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-3-startService-%EF%BC%9A%E4%B8%8D%E5%8F%AF%E4%BA%A4%E4%BA%92%E7%9A%84%E5%90%8E%E5%8F%B0%E6%9C%8D%E5%8A%A1"><span class="nav-number">1.2.3.</span> <span class="nav-text">1.2.3. startService()：不可交互的后台服务</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-4-bindService-%EF%BC%9A%E5%8F%AF%E4%BA%A4%E4%BA%92%E7%9A%84%E5%90%8E%E5%8F%B0%E6%9C%8D%E5%8A%A1"><span class="nav-number">1.2.4.</span> <span class="nav-text">1.2.4. bindService()：可交互的后台服务</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-5-%E5%89%8D%E5%8F%B0%E6%9C%8D%E5%8A%A1"><span class="nav-number">1.2.5.</span> <span class="nav-text">1.2.5. 前台服务</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-6-IntentService"><span class="nav-number">1.2.6.</span> <span class="nav-text">1.2.6. IntentService</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-3-Broadcast%EF%BC%9A%E5%B9%BF%E6%92%AD"><span class="nav-number">1.3.</span> <span class="nav-text">1.3. Broadcast：广播</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-1-%E5%B9%BF%E6%92%AD%E5%88%86%E7%B1%BB"><span class="nav-number">1.3.1.</span> <span class="nav-text">1.3.1. 广播分类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-2-%E5%AE%9A%E4%B9%89%E5%B9%BF%E6%92%AD%E6%8E%A5%E6%94%B6%E5%99%A8"><span class="nav-number">1.3.2.</span> <span class="nav-text">1.3.2. 定义广播接收器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-3-%E6%B3%A8%E5%86%8C%E5%B9%BF%E6%92%AD%E6%8E%A5%E6%94%B6%E5%99%A8"><span class="nav-number">1.3.3.</span> <span class="nav-text">1.3.3. 注册广播接收器</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%9D%99%E6%80%81%E6%B3%A8%E5%86%8C"><span class="nav-number">1.3.3.1.</span> <span class="nav-text">静态注册</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8A%A8%E6%80%81%E6%B3%A8%E5%86%8C"><span class="nav-number">1.3.3.2.</span> <span class="nav-text">动态注册</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-4-%E5%8F%91%E9%80%81%E5%B9%BF%E6%92%AD"><span class="nav-number">1.3.4.</span> <span class="nav-text">1.3.4. 发送广播</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%97%A0%E5%BA%8F%E5%B9%BF%E6%92%AD%EF%BC%9A%E6%89%80%E6%9C%89%E7%9A%84%E6%8E%A5%E6%94%B6%E8%80%85%E9%83%BD%E4%BC%9A%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6%EF%BC%8C%E4%B8%8D%E5%8F%AF%E4%BB%A5%E8%A2%AB%E6%8B%A6%E6%88%AA%EF%BC%8C%E4%B8%8D%E5%8F%AF%E4%BB%A5%E8%A2%AB%E4%BF%AE%E6%94%B9%E3%80%82"><span class="nav-number">1.3.4.1.</span> <span class="nav-text">无序广播：所有的接收者都会接收事件，不可以被拦截，不可以被修改。</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%9C%89%E5%BA%8F%E5%B9%BF%E6%92%AD%EF%BC%9A%E6%8C%89%E7%85%A7%E4%BC%98%E5%85%88%E7%BA%A7%EF%BC%8C%E4%B8%80%E7%BA%A7%E4%B8%80%E7%BA%A7%E7%9A%84%E5%90%91%E4%B8%8B%E4%BC%A0%E9%80%92%EF%BC%8C%E6%8E%A5%E6%94%B6%E8%80%85%E5%8F%AF%E4%BB%A5%E4%BF%AE%E6%94%B9%E5%B9%BF%E6%92%AD%E6%95%B0%E6%8D%AE%EF%BC%8C%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%BB%88%E6%AD%A2%E5%B9%BF%E6%92%AD%E4%BA%8B%E4%BB%B6%E3%80%82"><span class="nav-number">1.3.4.2.</span> <span class="nav-text">有序广播：按照优先级，一级一级的向下传递，接收者可以修改广播数据，也可以终止广播事件。</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-5-%E6%9C%AC%E5%9C%B0%E5%B9%BF%E6%92%AD"><span class="nav-number">1.3.5.</span> <span class="nav-text">1.3.5. 本地广播</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-4-ContentProvider"><span class="nav-number">1.4.</span> <span class="nav-text">1.4. ContentProvider</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#2-%E5%85%B6%E4%BB%96"><span class="nav-number">2.</span> <span class="nav-text">2. 其他</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#2-1-%E9%80%80%E5%87%BA%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%9A%84%E6%96%B9%E6%B3%95"><span class="nav-number">2.1.</span> <span class="nav-text">2.1. 退出应用程序的方法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-1-%E6%8C%89%E4%B8%A4%E4%B8%8B%E5%9B%9E%E9%80%80%E9%94%AE%E9%80%80%E5%87%BA%E5%BA%94%E7%94%A8%EF%BC%9A"><span class="nav-number">2.1.1.</span> <span class="nav-text">2.1.1. 按两下回退键退出应用：</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-2-System-exit-0"><span class="nav-number">2.1.2.</span> <span class="nav-text">2.1.2. System.exit(0);</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-3-%E6%8A%9B%E5%87%BA%E5%BC%82%E5%B8%B8%EF%BC%8C%E5%BC%BA%E5%88%B6%E9%80%80%E5%87%BA"><span class="nav-number">2.1.3.</span> <span class="nav-text">2.1.3. 抛出异常，强制退出</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-4-%E4%BD%BF%E7%94%A8Application%E9%80%80%E5%87%BA%EF%BC%9A%E8%87%AA%E8%A1%8C%E7%BB%B4%E6%8A%A4Activity%E5%88%97%E8%A1%A8"><span class="nav-number">2.1.4.</span> <span class="nav-text">2.1.4. 使用Application退出：自行维护Activity列表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-5-%E4%BD%BF%E7%94%A8%E5%B9%BF%E6%92%AD%E9%80%80%E5%87%BA"><span class="nav-number">2.1.5.</span> <span class="nav-text">2.1.5. 使用广播退出</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-2-Android-Context%E4%B8%8A%E4%B8%8B%E6%96%87"><span class="nav-number">2.2.</span> <span class="nav-text">2.2. Android Context上下文</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-3-Dalvik%E8%99%9A%E6%8B%9F%E6%9C%BA%E8%BF%9B%E7%A8%8B"><span class="nav-number">2.3.</span> <span class="nav-text">2.3. Dalvik虚拟机进程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-4-SpanableString%EF%BC%9AText%E8%A3%85%E9%A5%B0"><span class="nav-number">2.4.</span> <span class="nav-text">2.4. SpanableString：Text装饰</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-5-Notification%EF%BC%9A%E9%80%9A%E7%9F%A5"><span class="nav-number">2.5.</span> <span class="nav-text">2.5. Notification：通知</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-6-%E8%BF%9B%E7%A8%8B%E5%88%86%E7%B1%BB%E5%92%8C%E4%BC%98%E5%85%88%E7%BA%A7"><span class="nav-number">2.6.</span> <span class="nav-text">2.6. 进程分类和优先级</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-6-1-%E5%89%8D%E5%8F%B0%E8%BF%9B%E7%A8%8B"><span class="nav-number">2.6.1.</span> <span class="nav-text">2.6.1. 前台进程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-6-2-%E5%8F%AF%E8%A7%81%E8%BF%9B%E7%A8%8B"><span class="nav-number">2.6.2.</span> <span class="nav-text">2.6.2. 可见进程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-6-3-%E6%9C%8D%E5%8A%A1%E8%BF%9B%E7%A8%8B"><span class="nav-number">2.6.3.</span> <span class="nav-text">2.6.3. 服务进程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-6-4-%E5%90%8E%E5%8F%B0%E8%BF%9B%E7%A8%8B"><span class="nav-number">2.6.4.</span> <span class="nav-text">2.6.4. 后台进程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-6-5-%E7%A9%BA%E8%BF%9B%E7%A8%8B"><span class="nav-number">2.6.5.</span> <span class="nav-text">2.6.5. 空进程</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-7-Android%E4%BB%8B%E7%BB%8D"><span class="nav-number">2.7.</span> <span class="nav-text">2.7. Android介绍</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-7-1-%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84"><span class="nav-number">2.7.1.</span> <span class="nav-text">2.7.1. 系统架构</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-7-2-%E5%8E%86%E5%8F%B2%E7%89%88%E6%9C%AC"><span class="nav-number">2.7.2.</span> <span class="nav-text">2.7.2. 历史版本</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-7-3-%E6%89%93%E5%8C%85%E6%B5%81%E7%A8%8B"><span class="nav-number">2.7.3.</span> <span class="nav-text">2.7.3. 打包流程</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#3-%E8%87%AA%E5%AE%9A%E4%B9%89View"><span class="nav-number">3.</span> <span class="nav-text">3. 自定义View</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#3-1-%E7%BB%98%E5%88%B6%E8%BF%87%E7%A8%8B"><span class="nav-number">3.1.</span> <span class="nav-text">3.1. 绘制过程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-2-%E6%8E%A7%E5%88%B6%E7%BB%98%E5%88%B6%E9%A1%BA%E5%BA%8F"><span class="nav-number">3.2.</span> <span class="nav-text">3.2. 控制绘制顺序</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#4-%E4%BA%8B%E4%BB%B6%E5%88%86%E5%8F%91"><span class="nav-number">4.</span> <span class="nav-text">4. 事件分发</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#5-%E5%8A%A8%E7%94%BB"><span class="nav-number">5.</span> <span class="nav-text">5. 动画</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#5-1-%E5%B8%A7%E5%8A%A8%E7%94%BB"><span class="nav-number">5.1.</span> <span class="nav-text">5.1. 帧动画</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-%E8%A1%A5%E9%97%B4%E5%8A%A8%E7%94%BB%EF%BC%88%E8%A7%86%E5%9B%BE%E5%8A%A8%E7%94%BB%EF%BC%89"><span class="nav-number">5.2.</span> <span class="nav-text">5.2. 补间动画（视图动画）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-3-%E5%B1%9E%E6%80%A7%E5%8A%A8%E7%94%BB%EF%BC%883-0%E4%BB%A5%E4%B8%8A%EF%BC%8CAPI-11%EF%BC%89"><span class="nav-number">5.3.</span> <span class="nav-text">5.3. 属性动画（3.0以上，API 11）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-2-AsyncTask"><span class="nav-number">5.4.</span> <span class="nav-text">7.2. AsyncTask</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-3-EventBus"><span class="nav-number">5.5.</span> <span class="nav-text">7.3. EventBus</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#8-Intent"><span class="nav-number">6.</span> <span class="nav-text">8. Intent</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-9-1-%E6%98%BE%E5%BC%8FIntent"><span class="nav-number">6.0.1.</span> <span class="nav-text">2.9.1. 显式Intent</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-9-2-%E9%9A%90%E5%BC%8FIntent"><span class="nav-number">6.0.2.</span> <span class="nav-text">2.9.2. 隐式Intent</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%8F%82%E8%80%83%E6%96%87%E7%AB%A0"><span class="nav-number">7.</span> <span class="nav-text">参考文章</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="丘山月夜"
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name">丘山月夜</p>
  <div class="site-description" itemprop="description">君は空を見てるか,<br>風の音を聞いてるか</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">60</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">14</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">21</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">丘山月夜</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://mist.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Mist</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/muse.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
